簡單介紹完所有會用到的東西跟概念之後,接著要切入實做的層面,來看看是如何使用Opentelemetry SDK來產生遙測資料,那我今天會以官方提供的python code做介紹。
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import (
BatchSpanProcessor,
ConsoleSpanExporter,
)
provider = TracerProvider()
processor = BatchSpanProcessor(ConsoleSpanExporter())
provider.add_span_processor(processor)
# Sets the global default tracer provider
trace.set_tracer_provider(provider)
# Creates a tracer from the global tracer provider
tracer = trace.get_tracer("my.tracer.name")
def do_work():
with tracer.start_as_current_span("span-name") as span:
# do some work that 'span' will track
print("doing some work...")
# When the 'with' block goes out of scope, 'span' is closed for you
current_span = trace.get_current_span()
current_span.set_attribute("operation.value", 1)
current_span.set_attribute("operation.name", "Saying hello!")
current_span.set_attribute("operation.other-stuff", [1, 2, 3])
from opentelemetry import trace
tracer = trace.get_tracer(__name__)
with tracer.start_as_current_span("span-1"):
# Do something that 'span-1' tracks.
ctx = trace.get_current_span().get_span_context()
link_from_span_1 = trace.Link(ctx)
with tracer.start_as_current_span("span-2", links=[link_from_span_1]):
# Do something that 'span-2' tracks.
# The link in 'span-2' is causally associated it with the 'span-1',
# but it is not a child span.
pass
# These are the necessary import declarations
from opentelemetry import trace
from opentelemetry import metrics
from random import randint
from flask import Flask, request
import logging
# Acquire a tracer
tracer = trace.get_tracer("diceroller.tracer")
# Acquire a meter.
meter = metrics.get_meter("diceroller.meter")
# Now create a counter instrument to make measurements with
roll_counter = meter.create_counter(
"dice.rolls",
description="The number of rolls by roll value",
)
app = Flask(__name__)
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
@app.route("/rolldice")
def roll_dice():
# This creates a new span that's the child of the current one
with tracer.start_as_current_span("roll") as roll_span:
player = request.args.get('player', default = None, type = str)
result = str(roll())
roll_span.set_attribute("roll.value", result)
# This adds 1 to the counter for the given roll value
roll_counter.add(1, {"roll.value": result})
if player:
logger.warn("{} is rolling the dice: {}", player, result)
else:
logger.warn("Anonymous player is rolling the dice: %s", result)
return result
def roll():
return randint(1, 6)
上述就是建立tracer、meter的實例去負責產生span、metrics,如果清楚要追蹤哪一段程式碼的行動,可以自己像上述一樣定義Span的範圍。
如果換個狀況是,你像我一樣不清楚應該要追蹤哪一段,又或者我想對某一個套件的所有動作進行紀錄,最好可以自動去偵測我微服務的整個範圍,並且自動產生Span,我不想要一個一個加入Span。這個時候有個神兵利器就出現了,那就是「Instrumentation」
我可以使用 instrumentation-libraries針對特定的instrumentation套件偵測
pip install opentelemetry-instrumentation-{instrumented-library}
pip install -e ./instrumentation/opentelemetry-instrumentation-{integration}
pip install opentelemetry-instrumentation-httpx
以httpx為例:
import httpx
from opentelemetry.instrumentation.httpx import HTTPXClientInstrumentor
url = "https://some.url/get"
HTTPXClientInstrumentor().instrument()
with httpx.Client() as client:
response = client.get(url)
async with httpx.AsyncClient() as client:
response = await client.get(url)
但是這樣還是要修改程式碼,如果今天我是一個維運的角色,我必須得要trace,但是我不能動到程式碼,那我也可以自動偵測該微服務所使用的套件,一樣透過安裝Instrumentation套件,opentelemetry-bootstrap -a install
讓他偵測微服務所使用到的套件並安裝,最後直接用opentelemetry-instrument啟動微服務就可以了
pip install opentelemetry-distro
opentelemetry-bootstrap -a install
export OTEL_PYTHON_LOGGING_AUTO_INSTRUMENTATION_ENABLED=true
opentelemetry-instrument \
--traces_exporter console \
--metrics_exporter console \
--logs_exporter console \
--service_name dice-server \
flask run -p 8080
霹靂啪拉講了一堆,其實今天重點不在於程式碼。我想給跟我一樣是入門可觀測性的夥伴說,我自己的心得是,當你可以修改微服務的程式碼的時候,很多事情SDK都可以解決。但是今天如果你的角色,沒辦法修改微服務的程式碼的時候,你就只能透過其他的方式,讓Span去串起來,甚至現在能看到的範例,都還是以網頁框架flask舉例。
上述都是基於在同個且同類型微服務的情況下,所以我今天遇到的挑戰就是,如果今天是不同個微服務,不同個且不同種的微服務情況下又該怎麼解決。比如說現在常見的串流資料方式,透過mqtt協定來傳輸資料,從mqtt broker 到 confluent kafka 再到 後端,完全不知道在mqtt怎麼inject、extract,而且有些現成的解決方案,東西安裝好設定好就能用,我根本不會改到程式碼,所以也沒機會inject、extract,所以我也不知道怎麼讓這個流程的Span組成完整的Trace。
只能說頭好痛,超級麻煩
不過我相信One Piece只是放在這廣大的世界裡的一角,不是我找不到,只是我還沒找到。
今日小總結,產生遙測資料的方式有三種
另外小補充,曾經有問過某個大大相關的問題,那我也得到一個警示就是,雖然不用動到程式碼,但是可能會有效能上的問題。
Opentelemetry python libraries
Opentelemetry instrumentation
Opentelemetry Python zero-code instrumentation